package com.bagus.mediapipefacedetection.manager;


import com.bagus.mediapipefacedetection.camera.CameraFactory;
import com.bagus.mediapipefacedetection.quality.DetectQualityInfo;
import com.bagus.mediapipefacedetection.quality.DetectQualityStatus;
import com.bagus.mediapipefacedetection.quality.DetectQualityThreshold;

import java.util.ArrayList;
import java.util.List;

public class DetectQualityManager {
    private static final String TAG = "DetectQualityManager";
    private DetectQualityThreshold threshold;
    private int frameKeepingCount = 0;
    private List<DetectQualityStatus> statusContainer = new ArrayList<>();
    private static final int DETECT_FRAME_COUNT = 10;

    private DetectQualityManager() {
        threshold = new DetectQualityThreshold();
    }

    public static DetectQualityManager getInstance() {
        return HOLDER.INSTANCE;
    }

    private static final class HOLDER {
        private final static DetectQualityManager INSTANCE = new DetectQualityManager();
    }

    public int setThreshold(DetectQualityThreshold qualityThreshold) {
        if (threshold == null) {
            return -1;
        }
        threshold.setFaceConfidence(qualityThreshold.getFaceConfidence());
        threshold.setFaceOffsetLeft(qualityThreshold.getFaceOffsetLeft());
        threshold.setFaceOffsetTop(qualityThreshold.getFaceOffsetTop());
        threshold.setFaceOffsetRight(qualityThreshold.getFaceOffsetRight());
        threshold.setFaceOffsetBottom(qualityThreshold.getFaceOffsetBottom());
        threshold.setFaceMinSizeRatio(qualityThreshold.getFaceMinSizeRatio());
        threshold.setFaceMaxSizeRatio(qualityThreshold.getFaceMaxSizeRatio());
        threshold.setFaceCenterRectX(qualityThreshold.getFaceCenterRectX());
        threshold.setFaceCenterRectY(qualityThreshold.getFaceCenterRectY());
        threshold.setFaceOffsetPitch(qualityThreshold.getFaceOffsetPitch());
        threshold.setFaceOffsetYaw(qualityThreshold.getFaceOffsetYaw());
        threshold.setFaceOffsetRoll(qualityThreshold.getFaceOffsetRoll());
        threshold.setFaceImageCutDownOffset(qualityThreshold.getFaceImageCutDownOffset());
        threshold.setNeedJudgeCoverMouth(qualityThreshold.isNeedJudgeCoverMouth());
        threshold.setNeedJudgeCoverEye(qualityThreshold.isNeedJudgeCoverEye());
        threshold.setNeedJudgeBlockEye(qualityThreshold.isNeedJudgeBlockEye());
        threshold.setNeedHolding(qualityThreshold.getNeedHolding());
        threshold.setPictureWidth(qualityThreshold.getPictureWidth());
        threshold.setPictureHeight(qualityThreshold.getPictureHeight());
        return 0;
    }

    public DetectQualityThreshold getThreshold() {
        return threshold;
    }

    private DetectQualityStatus getFaceQualityStatus(DetectQualityInfo info) {
        if (info == null ) {
            return DetectQualityStatus.MGFacePPSkinAICameraFaceNotFound;
        }
        DetectQualityStatus status = DetectQualityStatus.MGFacePPSkinAICameraFaceNone;
        float faceWidthRatio = info.getFaceWidthRate();
        float faceLeft = info.getFaceRate()[0];
        float faceRight = info.getFaceRate()[2];
        float faceTop = info.getFaceRate()[1];
        float faceBottom = info.getFaceRate()[3];
        float headTop = info.getHeadRate()[1];
        float headBottom = info.getHeadRate()[3];
//        float faceWidthRatio = (info.getFaceRect().bottom - info.getFaceRect().top) / (info.getOriginalImageSize().y * 1.0f);
//        float faceHeightRatio = (info.getFaceRect().right - info.getFaceRect().left) / (info.getOriginalImageSize().x * 1.0f);
//        float faceX = 1 - info.getFaceRect().bottom / (info.getOriginalImageSize().y * 1.0f);
//        float faceY = info.getFaceRect().left / (info.getOriginalImageSize().x * 1.0f);
        float FaceCenterX = faceLeft + faceWidthRatio/2;
//        float FaceCenterY = faceY + faceHeightRatio / 2;





        float faceHeightRatio = faceBottom-faceTop;
//        float FaceCenterX = faceX + faceWidthRatio / 2;
        float FaceCenterY = faceTop + faceHeightRatio / 2;

        if (faceWidthRatio > threshold.getFaceMaxSizeRatio()) {
//            ILogPrint.loge(TAG, "MGFacePPSkinAICameraFaceTooLarge");
            status = DetectQualityStatus.MGFacePPSkinAICameraFaceTooLarge;
        }

        else if (faceWidthRatio < threshold.getFaceMinSizeRatio()) {
//            ILogPrint.loge(TAG, "MGFacePPSkinAICameraFaceTooSmall");
            status = DetectQualityStatus.MGFacePPSkinAICameraFaceTooSmall;
        }else{
            if (FaceCenterX - threshold.getFaceCenterRectX() > threshold.getFaceOffsetLeft()) {
//            ILogPrint.loge(TAG, "MGFacePPSkinAICameraFaceNeedLeft");
                status =  DetectQualityStatus.MGFacePPSkinAICameraFaceNeedLeft;
            }
            //threshold.getFaceCenterRectX() - FaceCenterX > threshold.getFaceOffsetTop()   faceRight > threshold.getFaceMaxSizeRatio()+threshold.getFaceOffsetRight()
            if (threshold.getFaceCenterRectX() - FaceCenterX > threshold.getFaceOffsetRight()) {
//            ILogPrint.loge(TAG, "MGFacePPSkinAICameraFaceNeedTop");
                status =  DetectQualityStatus.MGFacePPSkinAICameraFaceNeedRight;
            }

            if (faceTop < threshold.getFaceOffsetTop()) {
//            ILogPrint.loge(TAG, "MGFacePPSkinAICameraFaceNeedRight");
                status =  DetectQualityStatus.MGFacePPSkinAICameraFaceNeedBottom;
            }
            if (headBottom > threshold.getFaceOffsetBottom()) {
//            ILogPrint.loge(TAG, "MGFacePPSkinAICameraFaceNeedBottom");
                status =  DetectQualityStatus.MGFacePPSkinAICameraFaceNeedTop;
            }
        }



        //头部欧拉角
        if (Math.abs(info.getFacePitch()) > threshold.getFaceOffsetPitch() ||
                Math.abs(info.getFaceYaw()) > threshold.getFaceOffsetYaw() ||
                Math.abs(info.getFaceRoll()) > threshold.getFaceOffsetRoll()) {
            status =  DetectQualityStatus.MGFacePPSkinAICameraFaceAlignCenter;
        }

//        if (info.getFacePitch() > threshold.getFaceOffsetPitch() ||
//                info.getFaceYaw() > threshold.getFaceOffsetYaw()
////                info.getFaceRoll() > threshold.getFaceOffsetRoll()
//        ) {
//            status = DetectQualityStatus.MGFacePPSkinAICameraFaceAlignCenter;
//        }

        if (info.isCoverEye() && threshold.isNeedJudgeCoverEye()) {
//            ILogPrint.loge(TAG, "MGFacePPSkinAICameraFaceKeepOutEye");
            status = DetectQualityStatus.MGFacePPSkinAICameraFaceKeepOutEye;
        }

        if (info.isCoverMouth() && threshold.isNeedJudgeCoverMouth()) {
//            ILogPrint.loge(TAG, "MGFacePPSkinAICameraFaceKeepOutMouth");
            status = DetectQualityStatus.MGFacePPSkinAICameraFaceKeepOutMouth;
        }

        if (status != DetectQualityStatus.MGFacePPSkinAICameraFaceNone) {
            frameKeepingCount = 0;
            return status;
        }

        if (threshold.isNeedJudgeBlockEye()) {
            if (!info.isBlockEye()) {
                frameKeepingCount = 0;
                status = DetectQualityStatus.MGFacePPSkinAICameraFaceCloseEyes;
            } else {
                frameKeepingCount ++;
                status = DetectQualityStatus.MGFacePPSkinAICameraFaceKeeping;
            }
        } else {
            status = DetectQualityStatus.MGFacePPSkinAICameraFaceKeeping;
            frameKeepingCount++;
        }
        if (frameKeepingCount > threshold.getNeedHolding()) {
//            ILogPrint.loge(TAG, "MGFacePPSkinAICameraFaceFinish");
            status = DetectQualityStatus.MGFacePPSkinAICameraFaceFinish;
        }
        return status;
    }

    public DetectQualityStatus getDetectQualityStatusStable(DetectQualityInfo info) {
        DetectQualityStatus status = getFaceQualityStatus(info);
        if ( status == DetectQualityStatus.MGFacePPSkinAICameraFaceFinish) {
            return status;
        }

        return getMostStatus(status);
    }

    private DetectQualityStatus getMostStatus(DetectQualityStatus status) {
        statusContainer.add(status);
        if (statusContainer.size() < DETECT_FRAME_COUNT) {
            return DetectQualityStatus.MGFacePPSkinAICameraFaceNone;
        }
        int [] statusCount = new int[DetectQualityStatus.MGFacePPSkinAICameraFaceFinish.ordinal()];
        for (int i = 0; i < statusCount.length; i++) {
            statusCount[i] = 0;
        }
        for (int i = 0; i < statusContainer.size(); i++) {
            statusCount[statusContainer.get(i).ordinal()] ++;
        }
        statusContainer.clear();
        int index = 1;
        for (int i = 0; i < statusCount.length; i++) {
            if (statusCount[index] < statusCount[i]) {
                index = i;
            }
        }
        return DetectQualityStatus.values()[index];
     }
}
